const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const types = require("@babel/types");
const generator = require("@babel/generator").default;
const fs = require('fs');

// 读取文件
let encode_file = fs.readFileSync("./jy.js", {
    encoding: "utf-8"
});
// 转换为ast数
let ast = parser.parse(encode_file);


// 获取解密函数，并写入内存
let member_decode_js = '';

for(let i=0;i<=4;i++){
    member_decode_js += generator(ast.program.body[i], {compact:true}).code
    // delete AST_parse.program.body[i]
}
eval(member_decode_js);

// const visitor = {
//     CallExpression: {
//         enter:[replace_DVn]
//     }
// }

function replace_DVn(path) {
    var node = path.node;
    if(node.callee == undefined || node.callee.property == undefined)
        return;
    if(node.callee.property.name == "DVn"){
        var arg = node.arguments[0].value;
        var value = AXzPo.DVn(arg);
        path.replaceInline(types.valueToNode(value))
    }
}



//遍历所有的遍历存入数组
function get_name_Array(path){
    var node = path.node;
    if(node.declarations == undefined
    || node.declarations.length != 3
    || node.declarations[0].init == undefined
    || node.declarations[0].init.property == undefined)
        return;
    if(node.declarations[0].init.property.name != "DVn")
        return;
    let varName1 = node.declarations[0].id.name;
    let varname2 = node.declarations[2].id.name;
    nameArray.push(varName1,varname2);
}

//定义一个用于存放变量名的数组
var nameArray = [];

const visitor = {
    //这里的VariableDeclaration要放在CallExpression的前面
    VariableDeclaration:{
        enter:[get_name_Array,Del_DVn]
    },
    CallExpression: {
        enter:[replace_name_Array,replace_DVn]
    },
    StringLiteral:{
        enter:[replace_unicode]
    },
    ForStatement:{
        enter:[replace_ForStatement]
    }
}

// 还原控制流平坦
function replace_ForStatement(path) {
    var node = path.node;

    // 获取上一个节点，也就是VariableDeclaration
    var PrevSibling = path.getPrevSibling();

    // 判断上个节点的各个属性，防止报错
    if (PrevSibling.container == undefined
        || PrevSibling.container[0].declarations == undefined
        || PrevSibling.container[0].declarations[0].init == undefined
        || PrevSibling.container[0].declarations[0].init.object == undefined
        || PrevSibling.container[0].declarations[0].init.object.object == undefined)
        return;

    if (PrevSibling.container[0].declarations[0].init.object.object.callee.property.name != 'Ecs')
        return;

    // SwitchStatement节点
    var body = node.body.body;

    if(body == undefined)
        return;

    // 判断当前节点的body[0]属性和body[0].discriminant是否存在
    if (!types.isSwitchStatement(body[0]))
        return;
    if (!types.isIdentifier(body[0].discriminant))
        return;

    // 获取控制流的初始值   var SXP = AXzPo.Ecs()[2][14]
    var argNode = PrevSibling.container[0].declarations[0].init;
    var init_arg_f = argNode.object.property.value;
    var init_arg_s = argNode.property.value;
    var init_arg = AXzPo.Ecs()[init_arg_f][init_arg_s];

    // 提取for节点中的if判断参数的value作为判断参数 AXzPo.Ecs()[4][13]
    var break_arg_f = node.test.right.object.property.value;
    var break_arg_s = node.test.right.property.value;
    var break_arg = AXzPo.Ecs()[break_arg_f][break_arg_s];

    // 提取switch下所有的case
    var case_list = body[0].cases;
    var resultBody = [];

    // 遍历全部的case
    for (var i = 0; i < case_list.length; i++) {
        for (; init_arg != break_arg;) {

            // 提取并计算case后的条件判断的值
            var case_arg_f = case_list[i].test.object.property.value;
            var case_arg_s = case_list[i].test.property.value;
            var case_init = AXzPo.Ecs()[case_arg_f][case_arg_s];

            if (init_arg == case_init) {
                //当前case下的所有节点
                var targetBody = case_list[i].consequent;

                // 删除break节点，和break节点的上一个节点的一些无用代码
                if (types.isBreakStatement(targetBody[targetBody.length - 1])
                    && types.isExpressionStatement(targetBody[targetBody.length - 2])
                    && targetBody[targetBody.length - 2].expression.right.object.object.callee.object.name == "AXzPo") {

                    // 提取break节点的上一个节点AJgjJ.EMf()后面的两个索引值
                    var change_arg_f = targetBody[targetBody.length - 2].expression.right.object.property.value;
                    var change_arg_s = targetBody[targetBody.length - 2].expression.right.property.value;

                    // 修改控制流的初始值
                    init_arg = AXzPo.Ecs()[change_arg_f][change_arg_s];

                    targetBody.pop(); // 删除break
                    targetBody.pop(); // 删除break节点的上一个节点
                }
                //删除break
                else if (types.isBreakStatement(targetBody[targetBody.length - 1])) {
                    targetBody.pop();
                }
                resultBody = resultBody.concat(targetBody);
                break;
            } else {
                break;
            }
        }
    }
    //替换for节点，多个节点替换一个节点用replaceWithMultiple
    path.replaceWithMultiple(resultBody);

    //删除上一个节点
    PrevSibling.remove();
}

//还原unicode编码,删除extra，这个地方添加‘/’更好
function replace_unicode(path) {
    var node = path.node;
    if(node.extra == undefined)
        return
    delete node.extra;
}

//删除多余的DVn类型的节点
function Del_DVn(path) {
    var node = path.node;
    var arrNode = node.declarations;

    //遍历arrNode节点，判断并删除DVn节点
    for(var i = 0;i < arrNode.length; i++){
        //判断是否为DVn节点
        if(arrNode[i].init == undefined || arrNode[i].init.property == undefined)
            break;
        if(arrNode[i].init.property.name != "DVn")
            break;
        path.remove();

        //删除下个节点
        var nextPath = path.getNextSibling();
        nextPath.remove();

        //删除下下个节点
        var nnextPath = nextPath.getNextSibling();
        nnextPath.remove();
        return;
    }
}

//替换存在数组中的变量
function replace_name_Array(path){
    var node = path.node;
    if(node.callee == undefined || node.callee.name == undefined)
        return;
    if(nameArray.indexOf(node.callee.name) == -1)
        return;
    var arg = node.arguments[0].value;
    var value = AXzPo.DVn(arg);
    path.replaceInline(types.valueToNode(value))
}

traverse(ast, visitor);

//将js还原后输出，去除了 \u
let {code} = generator(ast,opts = {jsescOption:{"minimal":true}});
fs.writeFile('text_after.js', code, (err) => {
});





// const visitor =
//     {
//         "Identifier|BinaryExpression"(path){
//             let {confident,value} = path.evaluate();
//             if (confident){
//                 path.replaceInline(types.valueToNode(value))
//             }
//         }
//
//     };
//
// // 调用插件，处理源代码
// traverse(ast, visitor);
//
// //生成新的 js code,并且保存到文件中输出
// let {code} = generator(ast,opts = {jsescOption:{"minimal":true}});
// fs.writeFile('text_after.js', code, (err) => {
// });
